package code.juc.producerconsumermodel;

import java.util.LinkedList;

/**
 * 生产者消费者模式
 * <p>
 * 1. 自己实现数据的安全性; 而不是直接使用线程安全的队列.
 */
public class ProducerAndConsumerModel {

    public static void main(String[] args) {
        Storage<Double> storage = new Storage<>(10);
        Thread producer = new Thread(new Producer(storage));
        Thread consumer = new Thread(new Consumer(storage));

        producer.start();
        consumer.start();
    }
}

class Storage<E> {
    private int maxSize;

    private LinkedList<E> data;

    public Storage(int maxSize) {
        this.maxSize = maxSize;
        data = new LinkedList<>();
    }

    public synchronized void put(E e) {
        try {
            while (data.size() == maxSize) {
                wait();
            }

            data.addLast(e);
            System.out.println(String.format("存入元素: %s, 现有元素个数: %d", e, data.size()));
            notify();
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }

    public synchronized void take() {
        try {
            while (data.isEmpty()) {
                wait();
            }

            System.out.println(String.format("取出元素: %s, 剩余元素个数: %d", data.pollFirst(),
                    data.size()));
            notify();
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}

class Producer implements Runnable {

    private Storage<Double> storage;

    public Producer(Storage<Double> storage) {
        this.storage = storage;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            storage.put(Math.random());
        }
    }
}

class Consumer implements Runnable {

    private Storage<Double> storage;

    public Consumer(Storage<Double> storage) {
        this.storage = storage;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            storage.take();
        }
    }
}


